package org.chen.aao.user.utils;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.security.Keys;
import lombok.extern.slf4j.Slf4j;
import org.chen.aao.common.exception.BusinessException;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.crypto.SecretKey;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

@Slf4j
@Component
public class JwtUtil {
    
    @Value("${jwt.secret}")
    private String secret;
    
    @Value("${jwt.expiration:86400000}") // 默认24小时
    private Long expiration;

    @Value("${jwt.refresh-expiration:604800000}") // 默认7天
    private Long refreshExpiration;

    @Value("${jwt.issuer:AI-Toolbox}")
    private String issuer;
    
    private SecretKey getSigningKey() {
        return Keys.hmacShaKeyFor(secret.getBytes());
    }
    
    public String generateToken(Long userId, String email) {
        Map<String, Object> claims = new HashMap<>();
        claims.put("userId", userId);
        claims.put("email", email);
        claims.put("tokenType", "ACCESS");
        return createToken(claims, email, expiration);
    }

    /**
     * 生成刷新Token
     */
    public String generateRefreshToken(Long userId) {
        Map<String, Object> claims = new HashMap<>();
        claims.put("userId", userId);
        claims.put("tokenType", "REFRESH");
        claims.put("tokenId", UUID.randomUUID().toString()); // 用于黑名单管理
        return createToken(claims, String.valueOf(userId), refreshExpiration);
    }

    /**
     * 创建Token
     */
    private String createToken(Map<String, Object> claims, String subject, Long expiration) {
        Date now = new Date();
        Date expiryDate = new Date(now.getTime() + expiration);

        return Jwts.builder()
                .claims(claims)
                .subject(subject)
                .issuer(issuer)
                .issuedAt(now)
                .expiration(expiryDate)
                .signWith(getSigningKey(), Jwts.SIG.HS256)
                .compact();
    }

    public Claims getClaimsFromToken(String token) {
        try {
            return Jwts.parser()
                    .verifyWith(getSigningKey())
                    .build()
                    .parseSignedClaims(token)
                    .getPayload();
        } catch (Exception e) {
            log.error("JWT解析失败: {}", e.getMessage());
            return null;
        }
    }

    /**
     * 从Token中提取邮箱
     */
    public String extractEmail(String token) {
        Claims claims = getClaimsFromToken(token);
        return claims.get("email", String.class);
    }

    /**
     * 从Token中提取主题（Subject）
     */
    public String extractSubject(String token) {
        return getClaimsFromToken(token).getSubject();
    }

    /**
     * 检查Token是否过期
     */
    public boolean isTokenExpired(String token) {
        try {
            Date expiration = getClaimsFromToken(token).getExpiration();
            return expiration.before(new Date());
        } catch (Exception e) {
            return true;
        }
    }

    public boolean validateToken(String token) {
        try {
            Jwts.parser()
                    .verifyWith(getSigningKey())
                    .build()
                    .parseSignedClaims(token);
            return false;
        } catch (Exception e) {
            log.error("JWT验证失败: {}", e.getMessage());
            return true;
        }
    }

    public Long getUserIdFromToken(String token) {
        Claims claims = getClaimsFromToken(token);
        if (claims != null) {
            return claims.get("userId", Long.class);
        }
        return null;
    }

    /**
     * 验证Token并返回用户ID
     */
    public Long validateTokenAndGetUserId(String token) {
        if (validateToken(token)) {
            throw new BusinessException("Token无效或已过期");
        }
        return getUserIdFromToken(token);
    }

    /**
     * 检查是否为访问Token
     */
    public boolean isAccessToken(String token) {
        try {
            Claims claims = getClaimsFromToken(token);
            String tokenType = claims.get("tokenType", String.class);
            return "ACCESS".equals(tokenType);
        } catch (Exception e) {
            return false;
        }
    }
    /**
     * 检查是否为刷新Token
     */
    public boolean isRefreshToken(String token) {
        try {
            Claims claims = getClaimsFromToken(token);
            String tokenType = claims.get("tokenType", String.class);
            return "REFRESH".equals(tokenType);
        } catch (Exception e) {
            return false;
        }
    }

    /**
     * 获取Token的剩余有效时间（秒）
     */
    public long getTokenRemainingTime(String token) {
        try {
            Date expiration = getClaimsFromToken(token).getExpiration();
            long remainingMillis = expiration.getTime() - System.currentTimeMillis();
            return remainingMillis > 0 ? remainingMillis / 1000 : 0;
        } catch (Exception e) {
            return 0;
        }
    }

    /**
     * 从Token中提取Token ID（用于刷新Token的黑名单管理）
     */
    public String extractTokenId(String token) {
        try {
            Claims claims = getClaimsFromToken(token);
            return claims.get("tokenId", String.class);
        } catch (Exception e) {
            return null;
        }
    }

    /**
     * 生成带有自定义Claims的Token
     */
    public String generateCustomToken(Map<String, Object> customClaims, String subject, Long customExpiration) {
        Map<String, Object> claims = new HashMap<>(customClaims);
        return createToken(claims, subject, customExpiration != null ? customExpiration : expiration);
    }
}